package tchk.xyz.lingyuntutorminiprogram.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import tchk.xyz.lingyuntutorminiprogram.dto.LoginDTO;
import tchk.xyz.lingyuntutorminiprogram.dto.UserDTO;
import tchk.xyz.lingyuntutorminiprogram.dto.UserInfoDTO;
import tchk.xyz.lingyuntutorminiprogram.dto.WxLoginResponseDTO;
import tchk.xyz.lingyuntutorminiprogram.dto.WxSessionDTO; // 导入WxSessionDTO类
import tchk.xyz.lingyuntutorminiprogram.entity.SysPermission;
import tchk.xyz.lingyuntutorminiprogram.entity.SysRole;
import tchk.xyz.lingyuntutorminiprogram.entity.SysUser;
import tchk.xyz.lingyuntutorminiprogram.entity.SysUserRole;
import tchk.xyz.lingyuntutorminiprogram.exception.CustomException;
import tchk.xyz.lingyuntutorminiprogram.mapper.SysUserMapper;
import tchk.xyz.lingyuntutorminiprogram.service.ISysRoleService;
import tchk.xyz.lingyuntutorminiprogram.service.ISysUserRoleService;
import tchk.xyz.lingyuntutorminiprogram.service.IUserService;
import tchk.xyz.lingyuntutorminiprogram.utils.JwtUtil;

import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统统一用户表 服务实现类
 * </p>
 *
 * @author Tchk
 * @since 2025-10-21
 */
@Service // 告诉Spring这是一个Service实现，把它交给Spring容器管理
public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements IUserService {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private ISysUserRoleService sysUserRoleService;

    //【新增】微信小程序登录逻辑的实现
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private ISysRoleService sysRoleService;

    @Value("${wx.miniapp.appid}")
    private String appid;
    @Value("${wx.miniapp.secret}")
    private String secret;

    @Override
    public SysUser getOneByOpenid(String openid) {
        return this.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getOpenid, openid));
    }

    @Override
    public String adminLogin(LoginDTO loginDTO) {
        // 1. 根据用户名查询数据库
        SysUser user = this.getOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getUsername, loginDTO.getUsername()));

        // 2. 判断用户是否存在
        if (user == null) {
            throw new CustomException("用户名或密码错误");
        }

        // 3. 比对密码
        // 前端传来的明文密码 vs 数据库中存储的加密密码
        if (!passwordEncoder.matches(loginDTO.getPassword(), user.getPassword())) {
            throw new CustomException("用户名或密码错误");
        }

        // 4. 判断账户状态
        if (user.getStatus() == 0) {
            throw new CustomException("账户已被禁用");
        }

        // 5. 登录成功，生成JWT令牌
        return jwtUtil.generateToken(user);
    }

    @Override
    public Long countTodayNewUsers() {
        LocalDate today = LocalDate.now();
        return this.count(new LambdaQueryWrapper<SysUser>()
                .ge(SysUser::getCreateTime, today.atStartOfDay()));
    }

    @Override
    public IPage<UserDTO> getUserList(IPage<UserDTO> page, String nickname) {
        return this.baseMapper.findUserList(page, nickname);
    }

    @Override
    @Transactional
    public void updateUserWithRoles(UserDTO userDTO) {
        // 1. 更新用户基本信息 (如状态)
        SysUser user = new SysUser();
        user.setId(userDTO.getId());
        user.setStatus(userDTO.getStatus());
        this.updateById(user);

        // 2. 删除该用户旧的所有角色关联
        sysUserRoleService.remove(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userDTO.getId()));

        // 3. 保存新的用户角色关联关系
        List<Long> roleIds = userDTO.getRoleIds();
        if (roleIds != null && !roleIds.isEmpty()) {
            List<SysUserRole> relations = roleIds.stream().map(roleId -> {
                SysUserRole relation = new SysUserRole();
                relation.setUserId(userDTO.getId());
                relation.setRoleId(roleId);
                return relation;
            }).collect(Collectors.toList());
            sysUserRoleService.saveBatch(relations);
        }
    }

    @Override
    @Transactional
    public WxLoginResponseDTO wxLogin(String code) {
        // 1. 构造请求URL
        String url = String.format("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", appid, secret, code);

        // 2. [已修改] 使用RestTemplate请求并直接将结果转换为DTO对象
        WxSessionDTO sessionDTO = restTemplate.getForObject(url, WxSessionDTO.class);

        // 3. [已修改] 健壮的错误处理
        if (sessionDTO == null || sessionDTO.getOpenid() == null) {
            // 如果 sessionDTO 为空或 openid 为空，记录日志并抛出异常
            // log.error("调用微信登录接口失败: {}", sessionDTO != null ? sessionDTO.getErrmsg() : "返回结果为空");
            throw new CustomException("微信登录失败，请重试: " + (sessionDTO != null ? sessionDTO.getErrmsg() : ""));
        }

        // 4. [已修改] 从DTO对象中获取openid
        String openid = sessionDTO.getOpenid();

        // 5. 后续逻辑不变：查询或创建用户
        SysUser user = this.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getOpenid, openid));
        if (user == null) {
            user = new SysUser();
            user.setOpenid(openid);
            // 这里可以设置一个默认昵称和头像
            user.setNickname("微信用户" + System.currentTimeMillis() % 10000);
            user.setAvatarUrl("默认头像URL"); // 可以设置一个默认头像
            this.save(user);
        }

        // 6. 生成响应并返回
        return generateWxLoginResponse(user);
    }

    @Override
    @Transactional
    public WxLoginResponseDTO selectRole(String openid, String roleCode) {
        SysUser user = this.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getOpenid, openid));
        if (user == null) {
            throw new CustomException("用户不存在");
        }

        SysRole role = sysRoleService.getOne(new LambdaQueryWrapper<SysRole>().eq(SysRole::getCode, roleCode));
        if (role == null) {
            throw new CustomException("选择的角色不存在");
        }

        long count = sysUserRoleService.count(new LambdaQueryWrapper<SysUserRole>()
                .eq(SysUserRole::getUserId, user.getId())
                .eq(SysUserRole::getRoleId, role.getId()));
        if (count == 0) {
            SysUserRole userRole = new SysUserRole();
            userRole.setUserId(user.getId());
            userRole.setRoleId(role.getId());
            sysUserRoleService.save(userRole);
        }

        user.setCurrentRoleId(role.getId());
        this.updateById(user);

        // [核心修正] 调用新的私有方法，不再复用wxLogin
        return generateWxLoginResponse(user);
    }

    /**
     * [新增] 私有辅助方法，用于根据用户信息生成完整的登录响应
     */
    private WxLoginResponseDTO generateWxLoginResponse(SysUser user) {
        List<SysUserRole> userRoles = sysUserRoleService.list(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, user.getId()));
        List<Long> roleIds = userRoles.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());

        if (user.getCurrentRoleId() == null && !roleIds.isEmpty()) {
            user.setCurrentRoleId(roleIds.get(0));
            this.updateById(user);
        }

        String token = jwtUtil.generateToken(user);

        UserInfoDTO userInfoDTO = new UserInfoDTO();
        BeanUtils.copyProperties(user, userInfoDTO);
        userInfoDTO.setRoleIds(roleIds);

        // [核心修正] 为新的字段名赋值
        userInfoDTO.setHasParentRole(roleIds.contains(1L)); // 假设家长角色ID=1
        userInfoDTO.setHasTeacherRole(roleIds.contains(2L)); // 假设教师角色ID=2

        WxLoginResponseDTO response = new WxLoginResponseDTO();
        response.setToken(token);
        response.setUserInfo(userInfoDTO);

        return response;
    }

}